package cn.bytest.netty.handler;

import cn.bytest.netty.NettyChannel;
import cn.bytets.rpc.api.context.RpcAppContext;
import cn.bytets.rpc.api.message.*;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ThreadPoolExecutor;

public class ChannelRunnableHandler {

    private ThreadPoolExecutor executor;

    public ChannelRunnableHandler(ThreadPoolExecutor executor){
        this.executor = executor;
    }

    public void received(NettyChannel nettyChannel,Object msg){
        this.executor.execute(new InvokeTask(nettyChannel,msg));
    }

    class InvokeTask implements Runnable{

        private NettyChannel nettyChannel;
        private Object msg;

        public InvokeTask(NettyChannel nettyChannel,Object msg){
            this.nettyChannel = nettyChannel;
            this.msg = msg;
        }
        @Override
        public void run() {
            Request request = (Request)msg;
            try {
                RpcInvocation rpc = (RpcInvocation)request.getData();
                RpcAppContext app = RpcAppContext.getInstance();
                Object obj = app.getBean(rpc.getInterfaceName());

                Method method = obj.getClass().getMethod(rpc.getMethodName(), rpc.getParameterTypes());
                Object invoke = method.invoke(obj, rpc.getArguments());
                nettyChannel.send(ResponseBuild.build(request.getId(),
                        null,invoke));
            }catch (Throwable t){
                nettyChannel.send(ResponseBuild.buildErrorResponse(request,t));
            }
        }
    }
}
